package cm.tl.pms.util;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.text.NumberFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
public class ParamUtil {

    public static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }

    public static boolean isEmpty(String str) {
        return ((str == null) || (str.length() == 0) || StringUtils.isBlank(str) || "null".equals(str) || "undefined".equals(str));
    }

    public static boolean isEmpty(Integer str) {
        return ((str == null) || ((str + "").length() == 0) || "null".equals(str + ""));
    }

    public static boolean isEmpty(Long str) {
        return ((str == null) || ((str + "").length() == 0) || "null".equals(str + ""));
    }

    public static boolean isEmpty(Object str) {
        return ((str == null) || ((str + "").length() == 0) || StringUtils.isBlank(str + "") || "null".equals(str + "") || "{}".equals(str + "") || "[]".equals(str + ""));
    }

    public static boolean isMapEmpty(Map map) {
        return (map == null || map.isEmpty()) ? true : false;
    }

    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    public static boolean isNotEmpty(Object str) {
        return !isEmpty(str);
    }

    public static String toString(Object obj) {
        return (isEmpty(obj)) ? "" : obj.toString();
    }

    public static double toDouble(Object obj) {
        return isEmpty(obj) ? 0 : Double.parseDouble(obj.toString());
    }

    public static Integer toInteger(Object obj) {
        return isEmpty(obj) ? 0 : Integer.parseInt(obj.toString());
    }

    public static Integer toEInteger(Object obj) {
        return (isEmpty(obj)) ? 1 : Integer.parseInt(obj.toString());
    }

    public static Long toLong(Object obj) {
        return (isEmpty(obj)) ? 0L : Long.parseLong(obj.toString());
    }


    public static boolean regex(String text, String regex) {
        if (ParamUtil.isEmpty(text)) {
            return false;
        }
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(text);
        return m.find();
    }

    public static String regexGet(String text, String regex) {
        if (ParamUtil.isEmpty(text)) {
            return null;
        }
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(text);
        if (m.find()) {
            return m.group();
        }
        return null;
    }

    public static String regexGetGroup(String text, String regex, int group) {
        if (ParamUtil.isEmpty(text)) {
            return null;
        }
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(text);
        if (m.find()) {
            return m.group(group);
        }
        return null;
    }

    public static String regexGetAll(String text, String regex) {
        if (ParamUtil.isEmpty(text)) {
            return null;
        }
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(text);

        if (m.find()) {
            int count = m.groupCount();
            StringBuilder sb = new StringBuilder();
            for (int i = 1; i <= count; i++) {
                String group = m.group(i);
                if (ParamUtil.isNotEmpty(group)) {
                    sb.append(group);
                }
            }
            return sb.toString();
        }
        return null;
    }

    public static String regexMax(String text, String regex, String split) {
        if (ParamUtil.isEmpty(text)) {
            return null;
        }
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(text);

        String maxStructure = "";
        int maxCount = 0;

        while (m.find()) {
            String structure = m.group(); // 获取括号内部分
            // 计算数字个数
            int count = structure.split(split).length; // 通过分割符统计
            if (count > maxCount) {
                maxCount = count;
                maxStructure = m.group(); // 保存完整结构
            }
        }
        return maxStructure;
    }

    public static String regexAdd(String text, String regex, String left, String right) {
        if (ParamUtil.isEmpty(text)) {
            return null;
        }
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(text);
        StringBuffer buffer = new StringBuffer();
        while (m.find()) {
            String match = m.group();
            m.appendReplacement(buffer, left + match + right);
        }
        m.appendTail(buffer);
        return buffer.toString();
    }

    /**
     * 去除号码两边的空格
     *
     * @param para    原字符串
     * @param defalut 如果为空默认值
     * @return
     */
    public static String formatStr(String para, String defalut) {
        if (null != para) {
            para = para.trim();
            if ("".equals(para)) {
                return defalut;
            }
            return para;
        } else {
            return defalut;
        }
    }

    /**
     * 去除号码两边的空格
     *
     * @param para 原字符串
     * @return
     */
    public static String formatStr(String para) {
        if (null != para) {
            para = para.trim();
            if ("".equals(para)) {
                return null;
            }
            return para;
        } else {
            return null;
        }
    }


    public static String getParam(Object obj) {
        try {
            StringBuilder sb = new StringBuilder();
            Field[] fs = obj.getClass().getDeclaredFields();
            for (int i = 0; i < fs.length; i++) {
                Field f = fs[i];
                f.setAccessible(true);
                Object val = f.get(obj);
                if (val != null && !"".equals(val)) {
                    val = URLEncoder.encode(val.toString(), "UTF-8");
                    if (sb.length() == 0) {
                        sb.append(f.getName() + "=" + val);
                    } else {
                        sb.append("&" + f.getName() + "=" + val);
                    }
                }
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getMapParams(Map params) {
        try {
            StringBuilder sb = new StringBuilder();
            for (Object key : params.keySet()) {
                Object val = params.get(key);
                val = URLEncoder.encode(val.toString(), "UTF-8");
                if (sb.length() == 0) {
                    sb.append(key + "=" + val);
                } else {
                    sb.append("&" + key + "=" + val);
                }
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Map<String, Object> getRequest2Map(HttpServletRequest request) {
        Map<String, Object> res = new HashMap<String, Object>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                Object value = request.getParameter(en);
                res.put(en, value);
                if (null == res.get(en) || "".equals(res.get(en))) {
                    res.remove(en);
                }
            }
        }
        return res;
    }

    public static Map<String, String> getRequest2StringMap(HttpServletRequest request) throws Exception {
        Map<String, String> res = new HashMap<String, String>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                String value = request.getParameter(en);
                res.put(en, value);
                if (null == res.get(en) || "".equals(res.get(en))) {
                    res.remove(en);
                }
            }
        }
        return res;
    }

    public static JSONObject getJSONRequestParams(HttpServletRequest request) {
        JSONObject jsonObject = new JSONObject();
        try {
            Map<String, String[]> params = request.getParameterMap();
            for (String key : params.keySet()) {
                String[] values = params.get(key);
                for (int i = 0; i < values.length; i++) {
                    String value = values[i];
                    jsonObject.put(key, value);
                }
            }
        } catch (Exception e) {

        }
        return jsonObject;
    }


    public static String getInputParam(HttpServletRequest request) {
        String queryString = "";
        try {
            Map<String, String[]> params = request.getParameterMap();
            for (String key : params.keySet()) {
                String[] values = params.get(key);
                for (int i = 0; i < values.length; i++) {
                    String value = values[i];
                    queryString += key + "=" + value + "&";
                }
            }
        } catch (Exception e) {

        }
        return queryString;
    }

    public static String getInputParam(Map<String, String> params) {
        StringBuilder builder = new StringBuilder();
        for (String key : params.keySet()) {
            String value = params.get(key);
            builder.append(key).append("=").append(value).append("&");
        }
        return builder.toString();
    }

    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     *
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map<String, String> params) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);

        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (i == keys.size() - 1) {//拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        return prestr;
    }

    public static String getUrlParamsByMap(Map<String, Object> map) {
        if (map == null) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            sb.append(entry.getKey() + "=" + entry.getValue());
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = StringUtils.substringBeforeLast(s, "&");
        }
        return s;
    }

    public static String getUrlByMap(Map<String, String> map) {
        if (map == null) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            sb.append(entry.getKey() + "=" + entry.getValue());
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = StringUtils.substringBeforeLast(s, "&");
        }
        return s;
    }

    public static Map<String, String> paramToMap(String paramStr) {
        String[] params = paramStr.split("&");
        Map<String, String> resMap = new HashMap<>();
        for (int i = 0; i < params.length; i++) {
            String[] param = params[i].split("=");
            if (param.length >= 2) {
                String key = param[0];
                String value = param[1];
                for (int j = 2; j < param.length; j++) {
                    value += "=" + param[j];
                }
                resMap.put(key, value);
            }
        }
        return resMap;
    }

    public static Map<String, Object> objectToMap(Object obj) {
        if (obj == null) {
            return null;
        }

        Map<String, Object> map = null;
        try {
            map = new HashMap<>();
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (key.compareToIgnoreCase("class") == 0) {
                    continue;
                }
                Method getter = property.getReadMethod();
                Object value = getter != null ? getter.invoke(obj) : null;
                map.put(key, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return map;
    }

    public static Map<String, String> objectToMap2(Object obj) {
        if (obj == null) {
            return null;
        }

        Map<String, String> map = null;
        try {
            map = new HashMap<>();
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (key.compareToIgnoreCase("class") == 0) {
                    continue;
                }
                Method getter = property.getReadMethod();
                Object value = getter != null ? getter.invoke(obj) : null;
                map.put(key, ParamUtil.toString(value));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return map;
    }

    public static Map<String, Object> decodeBody(String body) {
        return Arrays.stream(body.split("&"))
                .map(s -> s.split("="))
                .collect(Collectors.toMap(arr -> arr[0], arr -> arr[1]));
    }

    public static String encodeBody(Map<String, Object> map) {
        return map.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining("&"));
    }

    public static Map<String, String> getMapFromStr(String body, String splitString) {
        Map<String, String> m = new HashMap<String, String>();
        if (isNotEmpty(body)) {
            String[] bas = body.split(splitString);
            for (String ba : bas) {
                if (ba.contains("=")) {
                    String[] b = ba.split("=");
                    if (b.length > 1 && !"null".equals(b[1])) {
                        if (b.length == 2) {
                            m.put(b[0], b[1]);
                        } else {
                            String tmp = b[0] + "=";
                            m.put(b[0], ba.substring(ba.indexOf(tmp) + tmp.length(), ba.length()));//去除第一个符合b[0]的字符串，留下其他的全部字符
                        }
                    } else {
                        m.put(b[0], "");
                    }
                }
            }
        }
        return m;
    }


    /**
     * 去除字符串中的空格、换行、制表符
     *
     * @param str
     * @return
     */
    public static String replaceBlank(String str) {
        String dest = "";
        if (str != null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }

    /**
     * 将String转为非null
     *
     * @param str
     * @return
     */
    public static String strNoNull(String str) {
        return isEmpty(str) ? "" : str;
    }

    /**
     * 将参数转为Integer ，为空则返回0
     *
     * @param obj
     * @return
     */
    public static Integer toInteger2(Object obj) {
        return isEmpty(obj) ? 0 : Integer.parseInt(obj.toString());
    }


    /**
     * 取字符串的第n个字符
     *
     * @param str    原字符串
     * @param n      第n个字符
     * @param isDESC 是否是倒序
     * @return
     */
    public static String getNsFromStr(String str, int n, boolean isDESC) {
        String nStr;
        if (ParamUtil.isEmpty(str)) {
            return null;
        }
        int length = str.length();
        if (length < n || n < 1) {
            return null;
        }
        if (isDESC) {
            nStr = str.substring(length - n, length - n + 1);
        } else {
            nStr = str.substring(n - 1, n);
        }
        return nStr;
    }

    /**
     * 必要时转换下
     *
     * @param jsonObject
     * @return
     */
    public static JSONObject convertJSONObject(JSONObject jsonObject) {
        return JSONObject.parseObject(jsonObject.toJSONString());
    }


    /**
     * double转化百分比字符串
     *
     * @return
     */
    public static String getPercentFormat(double d, int FractionDigits) {
        NumberFormat nf = NumberFormat.getPercentInstance();
        nf.setMinimumFractionDigits(FractionDigits);// 小数点后保留几位
        String str = nf.format(d);
        return str;
    }

    /**
     * 判断map是否为空
     */
    public static boolean checkMapIsEmpty(Map map) {
        if (ParamUtil.isEmpty(map)) {
            return true;
        } else {
            for (Object o : map.keySet()) {
                if ("pageSize".equals(o.toString()) || "currPage".equals(o.toString()) || "isVip".equals(o.toString()) || "type".equals(o.toString()) || "name".equals(o.toString()) || "uploadType".equals(o.toString())) {
                    continue;
                }
                if (ParamUtil.isNotEmpty(map.get(o.toString()))) {
                    return false;
                }
            }
        }
        return true;

    }

    public static boolean jsonValidate(String jsonStr) {
        try {
            if ("0".equals(JSONObject.parseObject(jsonStr).getString("status"))) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    public static boolean isSameIntegerList(List<Integer> list1, List<Integer> list2) {
        if (CollectionUtils.isEmpty(list1) && CollectionUtils.isEmpty(list2)) {
            return true;
        }
        if (list1.containsAll(list2) && list2.containsAll(list1)) {
            return true;
        }
        return false;
    }

    public static LinkedHashSet<Integer> ListToSet(List<Integer> list) {
        LinkedHashSet<Integer> set = new LinkedHashSet<>();
        if (CollectionUtils.isEmpty(list)) {
            return set;
        }
        for (Integer integer : list) {
            set.add(integer);
        }
        return set;
    }

    public static Map<String, String> getRequest2MapByChange(HttpServletRequest request, Map<String, String> changeMap) {
        try {
            Map<String, String> request2Map = getRequest2StringMap(request);
            if (!isMapEmpty(changeMap)) {
                request2Map.putAll(changeMap);
            }
            return request2Map;
        } catch (Exception e) {
            return new HashMap<>();
        }
    }


}
